//Definition file Convex.cpp
#include <vcl.h>
#include "Convex.h"

Convex::Convex()  {
        this->vertexList = new Lista<PV>;
};

Convex::~Convex(  ) {
        this->vertexList = new Lista<PV>;
};

void Convex::draw( ){
        if(!getVertexList(  )->vacia(  )){
                getVertexList(  )->inicia(  );
                glBegin(GL_POLYGON);
                        for(int i=0; i<getVertexList(  )->getLongitud(  );i++){
                                glVertex2f(getVertexList(  )->getActual(  )->getx(  ),getVertexList(  )->getActual(  )->gety(  ));
                                vertexList->avanza();
                        }
                glEnd();
         }
};

void Convex::drawCover(float width) {
         if(!getCoverVertexList(width)->vacia(  )){
                getCoverVertexList(width)->inicia(  );
                glBegin(GL_LINE_STRIP);
                        for(int i=0; i<getCoverVertexList(width)->getLongitud(  );i++){
                                glVertex2f(getCoverVertexList(width)->getActual(  )->getx(  ),getCoverVertexList(width)->getActual(  )->gety(  ));
                                coverVertexList->avanza();
                        }
                glEnd();
         }
};

void Convex::drawPerimeter(  ){
         if(!getVertexList(  )->vacia(  )){
                getVertexList(  )->inicia(  );
                glBegin(GL_LINE_STRIP);
                        for(int i=0; i<getVertexList(  )->getLongitud(  );i++){
                                glVertex2f(getVertexList(  )->getActual(  )->getx(),getVertexList(  )->getActual(  )->gety(  ));
                                vertexList->avanza(  );
                        }
                glEnd(  );
         }
};



bool Convex::colision(PV pointUbication, PV vector , PV& exit) {
/*
        pointUbication: The position of the ball
        vector: The direction of the ball
        exit: The resulting direction
*/

        GLfloat Tin  = -10000;
        GLfloat Tout =  10000;
        GLfloat distance = 10000;
        if (!coverVertexList->vacia()) {
                coverVertexList->inicia(  );
                // For each vertex on the convex polygon
                for (int i=0;i<coverVertexList->getLongitud(  );i++) {
                        PV V1 = *coverVertexList->getActual(  );
                        // Return to initial vertex when last vertex
                        if (i==coverVertexList->getLongitud(  )-1) {
                                coverVertexList->inicia();
                        } else {
                                coverVertexList->avanza(  );
                        }
                        PV V2 = *coverVertexList->getActual(  );

                        // Actual polygon segment
                        PV V1_V2= V2.restaPV( V1 );

                        // WTF?
                        PV V1_P = V1.restaPV( pointUbication );

                        // k = v*n / n*n
                        GLfloat numer = V1_P.prodEscalar(V1_V2.normal());
                        GLfloat denom = (V1_V2.normal()).prodEscalar(V1_V2.normal());
                        GLfloat k = numer / denom;

                        // vectorAux2 = kn
                        PV vectorAux2;
                        vectorAux2 = V1_V2.normal();
                        vectorAux2.escalacion(k);

                        // vectorAux = direction+kn
                        PV vectorAux = vector;
                        vectorAux = vectorAux.sumaPV(vectorAux2);

                        PV   tHit   = pointUbication.sumaPV(vectorAux2);
                        PV   aux1   = tHit.restaPV(V1);
                        PV   aux2   = tHit.restaPV(V2);

                        if (V1_V2.module() != 0) {
                                GLfloat tt1 = aux1.divisionPV(V1_V2);
                                GLfloat tt2 = aux2.divisionPV(V1_V2);

                                if(vector.prodEscalar(V1_V2.normal())<0){
                                        if(tt1>=-0.006 && tt1<=1.006 && tt2>=-0.006 && tt2<=1.006) {
                                                Tin = k;
                                                distance = vectorAux2.module();
                                                if ( distance > -vector.module() && distance < vector.module() ) {
                                                        // Calculate reflexion
                                                        // k = v*n / n*n
                                                        GLfloat numer2 = vector.prodEscalar(V1_V2.normal());
                                                        GLfloat denom2 = (V1_V2.normal()).prodEscalar(V1_V2.normal());
                                                        GLfloat k2 = numer2 / denom2;

                                                        // aux3 = 2kn
                                                        PV aux3 = V1_V2.normal();
                                                        aux3.escalacion(2*k2);

                                                        // vr = v - 2kn                                                // vr = v-2kn
                                                        exit = vector.restaPV(aux3);
                                                        return true;
                                                }
                                        }
                                }

                                if(vector.prodEscalar(V1_V2.normal())==0) {
                                        if(k>Tin)
                                                Tin=k;
                                }

                                if(vector.prodEscalar(V1_V2.normal())>0){
                                        if(k<Tout)
                                                Tout=k;
                                }
                        }
                }
                return ( distance > -vector.module() && distance < vector.module() );
        }
        return false;
}
